package com.exam.api.modules.goods.utils.youzan;

import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONArray;
import cn.hutool.json.JSONObject;
import cn.hutool.json.JSONUtil;
import com.exam.api.common.utils.RedisClient;
import jakarta.annotation.Resource;
import lombok.extern.log4j.Log4j2;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

@Log4j2
@Component
public class YZRequest {
    @Resource
    private RedisClient redisClient;

    private static final String APP_ID = "3df8ed79f2fafc3465";
    private static final String APP_SECRET = "429188ac1ce7c8275908e32cced06f95";
    private static final String URL = "https://open.youzanyun.com/";
    private static final String MERCHANT_CODE = "181687946";    //正式店铺

    public String decrypt(String source) {

//        "$dwczt05zRSC6xI79ZQSwhw==$1$"
        Map<String, Object> map = new HashMap<>();
        map.put("source", source);
        String execute = HttpUtil.post(URL + "api/youzan.cloud.secret.decrypt.single/1.0.0?access_token=" + getAccessToken(), JSONUtil.toJsonStr(map));
        JSONObject jsonObject = JSONUtil.parseObj(execute);
        if(!Objects.equals(jsonObject.getInt("code"), 200)){
            log.error("获取加密失败,");
        }
        return jsonObject.getStr("data");
    }
    public List<YZOrder> getOrderInfo(String orderId) throws IOException {
        Map<String, Object> map = new HashMap<>();
        map.put("tid",orderId);
        String execute = HttpUtil.post(URL + "api/youzan.trade.get/4.0.2?access_token=" + getAccessToken(), JSONUtil.toJsonStr(map));
        JSONObject jsonObject = JSONUtil.parseObj(execute);
        if(!Objects.equals(jsonObject.getInt("code"), 200)){
            log.error("获取订单信息失败,{}",jsonObject);
        }
        JSONObject data = jsonObject.getJSONObject("data");
        List<YZOrder> yzOrders = parseOrder(data);
        log.info(data);
        return yzOrders;
    }
    public List<YZOrder> getOrderList(LocalDateTime startTime, LocalDateTime endTime) {
        List<YZOrder> list = new ArrayList<>();
        Integer pageNo = 1;
        while (true){
            Map<String, Object> map = new HashMap<>();
            map.put("page_no", pageNo);
            map.put("start_success", startTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            map.put("end_success", endTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")));
            map.put("status", "TRADE_SUCCESS");
            map.put("page_size", 20);
            String execute = HttpUtil.post(URL + "api/youzan.trades.sold.get/4.0.4?access_token=" + getAccessToken(), JSONUtil.toJsonStr(map));
            JSONObject jsonObject = JSONUtil.parseObj(execute);
            log.info(execute);
            if(!Objects.equals(jsonObject.getInt("code"), 200)){
                log.error("获取订单失败,");
            }
            JSONObject data = jsonObject.getJSONObject("data");

            Integer totalCount = data.getInt("total_results");

            JSONArray items = data.getJSONArray("full_order_info_list");
            for (Object item : items) {
                JSONObject itemJson = (JSONObject) item;
                List<YZOrder> yzOrders = parseOrder(itemJson);
                list.addAll(yzOrders);
            }

            if(list.size() >= totalCount){
                break;
            }
            pageNo ++;
        }
        return list;
    }

    private List<YZOrder> parseOrder(JSONObject item) {
        List<YZOrder> list = new ArrayList<>();
        JSONObject fullOrderInfo = item.getJSONObject("full_order_info");
        JSONObject buyerInfo = fullOrderInfo.getJSONObject("buyer_info");
        String buyerPhone = buyerInfo.getStr("buyer_phone");
        if(StrUtil.isNotBlank(buyerPhone)){
            buyerPhone = decrypt(buyerPhone);
        }
        JSONObject orderInfo = fullOrderInfo.getJSONObject("order_info");
        String payTime = orderInfo.getStr("pay_time");
        String successTime = orderInfo.getStr("success_time");
        String orderId = orderInfo.getStr("tid");

        YZOrder yzOrder = new YZOrder();
        yzOrder.setOrderId(orderId);
        yzOrder.setBuyerPhone(buyerPhone);
        yzOrder.setPayTime(payTime);
        yzOrder.setSuccessTime(successTime);
        JSONArray orders = fullOrderInfo.getJSONArray("orders");
        for (Object order : orders) {
            JSONObject orderJson = (JSONObject) order;
            Long itemId = orderJson.getLong("item_id");
            Long skuId = orderJson.getLong("sku_id");
            String title = orderJson.getStr("title");
            yzOrder.setItemId(itemId);
            yzOrder.setItemTitle(title);
            yzOrder.setSkuId(skuId);
            list.add(yzOrder);
        }
        return list;
    }

    public List<YZProductSku> getProductSkuList(YZProduct  product){
        Map<String, Object> request = new HashMap<>();
        Map<String, Object> map = new HashMap<>();
        map.put("item_id", product.getItemId());
        map.put("channel", product.getChannel());
        map.put("kdt_id", product.getKdtId());
        request.put("request",map);
        String execute = HttpUtil.post(URL + "api/youzan.item.itemdetail.get/1.0.0?access_token=" + getAccessToken(), JSONUtil.toJsonStr(request));
        JSONObject jsonObject = JSONUtil.parseObj(execute);
        if(!Objects.equals(jsonObject.getInt("code"), 200)){
            log.error("获取商品失败,{}",jsonObject);
        }
        JSONObject data = jsonObject.getJSONObject("data");
        JSONArray skus = data.getJSONArray("skus");
        log.info(data);

        return skus.stream().map(item -> {
            JSONObject obj = (JSONObject) item;
            YZProductSku yzProductSku = new YZProductSku();
            yzProductSku.setSkuId(obj.getLong("sku_id"));
            yzProductSku.setItemId(product.getItemId());
            JSONArray specValues = obj.getJSONArray("spec_values");
            if(specValues.isEmpty()){
                yzProductSku.setSpecValueName("默认规格");
            }else {
                JSONObject specValue = (JSONObject) specValues.getFirst();
                yzProductSku.setSpecValueName(specValue.getStr("spec_value_name"));
            }

            return yzProductSku;
        }).collect(Collectors.toList());
    }

    public List<YZProduct> getProductList() throws IOException {
        List<YZProduct> list = new ArrayList<>();
        Integer pageNo = 1;
        while (true){
            Map<String, Object> map = new HashMap<>();
            map.put("page_no", pageNo);
            map.put("channel", 0);
            map.put("kdt_id", MERCHANT_CODE);
            map.put("page_size", 20);
            String execute = HttpUtil.post(URL + "api/youzan.item.base.search/1.0.0?access_token=" + getAccessToken(), JSONUtil.toJsonStr(map));
            JSONObject jsonObject = JSONUtil.parseObj(execute);
            if(!Objects.equals(jsonObject.getInt("code"), 200)){
                log.error("获取商品失败,");
            }
            JSONObject data = jsonObject.getJSONObject("data");
            log.info(data);
            JSONObject paginator = data.getJSONObject("paginator");
            JSONArray items = data.getJSONArray("items");
            Integer totalCount = paginator.getInt("total_count");
            list.addAll(items.toList(YZProduct.class));

            if(list.size() >= totalCount){
                break;
            }
            pageNo ++;
        }
        return list;
    }
    public YZAccessToken getAccessTokenResponse() throws IOException {
        Map<String, Object> map = new HashMap<>();
        map.put("client_id", APP_ID);
        map.put("client_secret", APP_SECRET);
        map.put("authorize_type", "silent");
        map.put("grant_id", MERCHANT_CODE);
        map.put("refresh", false);
        String execute = HttpUtil.post(URL + "auth/token", JSONUtil.toJsonStr(map));
        JSONObject jsonObject = JSONUtil.parseObj(execute);
        log.info(execute);
        if(!Objects.equals(jsonObject.getInt("code"), 200)){
            log.error("获取token失败,");
        }
        JSONObject data = jsonObject.getJSONObject("data");
        YZAccessToken accessToken = new YZAccessToken();
        accessToken.setAccessToken(data.getStr("access_token"));
        accessToken.setExpires(data.getLong("expires"));
        return accessToken;
    }


    public String getAccessToken(){
        String tokenKey = "YZ:ACCESS:TOKEN";
        String token = (String) redisClient.get(tokenKey);

        try{
            if(StrUtil.isBlank(token)){
                YZAccessToken accessTokenResponse = getAccessTokenResponse();
                token = accessTokenResponse.getAccessToken();

                long accessTokenExpiresAt = accessTokenResponse.getExpires();
                redisClient.set(tokenKey,token);

                redisClient.expire(tokenKey, (accessTokenExpiresAt - System.currentTimeMillis()) / 1000);
                log.info("生成了token:{} 过期时间：{}",token,accessTokenExpiresAt);
            }

        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return token;
    }

}
